package com.liaoyifan.core.aspect;

import com.liaoyifan.core.annotation.Idempotent;
import com.liaoyifan.core.util.Redis;
import com.liaoyifan.core.util.SpELKey;
import java.time.Duration;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;

@SuppressWarnings("unused")
@Aspect
@Order(4)
public class IdempotentAspect {

    private static final Logger log = LogManager.getLogger(IdempotentAspect.class.getSimpleName());

    @Around("@annotation(idempotent)")
    public Object idempotentAround(ProceedingJoinPoint joinPoint, Idempotent idempotent)
            throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String key = SpELKey.idempotentKey(signature, joinPoint.getArgs(), idempotent.value());
        Object exists = Redis.get(key);
        if (exists != null) {
            log.info("IdempotentKey Exists: {}", key);
            return exists;
        }
        Object result = joinPoint.proceed();
        Redis.set(key, result, Duration.ofSeconds(idempotent.expire()));
        log.info("IdempotentKey Set: {}", key);
        return result;
    }
}
